package com.yuewen.permissioncheck.asm;
import com.yuewen.permissioncheck.asm.checker.InvokeParam;
import com.yuewen.permissioncheck.asm.checker.PermissionChecker;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.AdviceAdapter;


/**
 * Created by zhanglulu on 2020/4/17.
 */

public class PermissionMethodVisitor extends AdviceAdapter {
    String mClassName = "";
    String mMethodName = "";
    //当前入参
    Object mEnterParm = "";

    protected PermissionMethodVisitor(MethodVisitor methodVisitor, int access, String className, String methodName, String desc) {
        super(Opcodes.ASM6, methodVisitor, access, methodName, desc);
        this.mMethodName = methodName;
        this. mClassName = className;
    }

    @Override
    public AnnotationVisitor visitAnnotation(String s, boolean b) {
        //Logger.d(methodName + ": visitAnnotation" + s);
        return super.visitAnnotation(s, b);
    }

    @Override
    protected void onMethodEnter() {
        super.onMethodEnter();
        //Logger.d(methodName + ": onMethodEnter");
    }

    @Override
    protected void onMethodExit(int i) {
        super.onMethodExit(i);
        //Logger.d(methodName + ": onMethodExit");
    }

    @Override
    public void visitLdcInsn(final Object cst) {
        super.visitLdcInsn(cst);
        mEnterParm = cst;
        Logger.d(mMethodName + " visitLdcInsn: " + cst);
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
        super.visitMethodInsn(opcode, owner, name, desc, itf);
       Logger.d("visitMethodInsn() called with: " +
         "opcode = [" + opcode + "], " +
         "owner = [" + owner + "]," +
         " name = [" + name + "], " +
         "className = [" + mClassName + "], " +
         "methodName = [" + mMethodName + "], " +
         "desc = [" + desc + "], " +
         "itf = [" + itf + "]");

        String invokeName = PermissionChecker.check(new InvokeParam(
          mClassName, mMethodName, name, mEnterParm, desc, owner
        ));
        if (invokeName != null && !invokeName.equals("")) {
            invokeHookHelper(invokeName);
        }
    }

    /**
     * 执行 hook helper
     */
    private void invokeHookHelper(String name) {
        visitMethodInsn(INVOKESTATIC,
                "com/yuewen/permissioncheck/HookPermissionHelper",
                name,
                "()V", false);
        Logger.d("insert: " + name + " curMethod: " + mMethodName);
    }
}
